# 若在 Windows 平台下编译，由于需要生成 ELF 格式的二进制文件，需要使用交叉编译工具此处使用的交叉编译工具为 LLVM-MinGW。
# 项目地址：https://github.com/mstorsjo/llvm-mingw
export MODE := DEBUG
ifeq ($(OS), Windows_NT)
	SHELL := pwsh.exe
	export CLANG :=  &"C:/toolchain/MSYS2/clang32/bin/i686-w64-mingw32-clang.exe"
	export LLD := &"C:/toolchain/MSYS2/clang32/bin/ld.lld.exe"
	export NASM := &"C:/toolchain/MSYS2/clang32/bin/nasm.exe"
else
	SHELL := pwsh
	export CLANG := clang
	export LLD := ld.lld
	export NASM := nasm
endif

ifeq ($(MODE), RELEASE)
	export OPTIMIZATION := -O3
	export MULTI_THREAD := -j8
else
	export OPTIMIZATION := -g3
endif
# 项目名称
export PROJECT_NAME := SimpleOS
# 平台
export PLATFORM := x86
# pwsh.exe执行命令参数
export .SHELLFLAGS := -NoProfile -Command
# 项目文件根目录，可能存在空格
# make 应使用带下划线的宏作为路径，如 _ROOT，其中空格被替换为 \空格 以确保空格能被正确处理
# powershell 应使用不带下划线的宏作为路径，如 ROOT 其中空格被替换为 `u{20} （`空格 也可以）以确保空格能被正确处理
export ROOT := $(shell (Get-Location).toString() -replace("\\", "/") -replace(" ", "``u{20}"))
export _ROOT := $(shell (Get-Location).toString() -replace("\\", "/") -replace(" ", "\ "))
# 源码文件路径
export SOURCE := $(ROOT)/source
export _SOURCE := $(_ROOT)/source
# 配置文件路径
export CONFIG := $(ROOT)/config
export _CONFIG := $(_ROOT)/config
# 构建路径
export BUILD := $(ROOT)/build
export _BUILD := $(_ROOT)/build
# 论文路径
export PAPER := $(ROOT)/Paper
export _PAPER := $(ROOT)/Paper
# 幻灯片路径
export SLIDE := $(ROOT)/Slide
export _SLIDE := $(ROOT)/Slide
# 模板路径
# TEMPLATE := $(ROOT)/template
# _TEMPLATE := $(_ROOT)/template
# 磁盘属性
DISK_FILE := hd_1GiB.img
# 操作系统镜像文件
IMG_NAME := $(PROJECT_NAME).img
# bochs配置文件名称
BOCHS_RUN_CONFIG := bochs-run.cfg
BOCHS_DEBUG_CONFIG := bochs-debug.cfg
# bochs运行日志文件名称
BOCHS_RUN_LOG := $(PROJECT_NAME)-run.log
# bochsdbg调试日志文件名称
BOCHS_DEBUG_LOG := $(PROJECT_NAME)-debug.log
# 操作系统模块
OS_MODULES :=  IO Kernel Utility IntExcept Memory ProcessThread FileSystem
# 所有模块
MODULES := Boot $(OS_MODULES) Program
# 操作系统待链接的目标文件
OBJECTS := $(addprefix $(BUILD)/, $(addsuffix .obj, $(OS_MODULES)))
TEST_PROGRAM := HELLO.EXE WORLD.EXE SYSTEM.EXE
VPATH:=$(_CONFIG) $(_BUILD)
# all: 构建所有需要构建的模块
# MODULES: 需要构建的各个模块
# Clean：清理解决方案
.PHONY : all Paper Slide Boot $(MODULES) Clean Binary Image

all: $(MODULES)
	New-Item -Type Directory -Path $(BUILD) -Force
	$(MAKE) Binary --file=Makefile.mk --directory=$(ROOT) SHELL="$(SHELL)"
	$(MAKE) Image --file=Makefile.mk --directory=$(ROOT) SHELL="$(SHELL)"

# 单独构建每个模块，采用部分链接方式分阶段产生 .obj，最后制作镜像时完成最终链接
$(MODULES):
	$(MAKE) $(MULTI_THREAD) --file=Makefile.mk --directory=$(SOURCE)/$@ SHELL="$(SHELL)" MODULE=$@
# 将各个 .obj 链接并重定向，入口为 SimpleMain
Binary:
	$(LLD) -o $(BUILD)/main.out $(OBJECTS) --image-base=0xC0065000 --entry=SimpleMain --verbose -m elf_i386
	objcopy --only-keep-debug $(BUILD)/main.out $(BUILD)/SimpleOS.dbg
	strip $(BUILD)/main.out -o $(BUILD)/SimpleOS.out
Image:
	qemu-img create -q -u $(BUILD)/$(IMG_NAME) 1G
# MBR 分区位于磁盘 0 号扇区
	dd if=$(BUILD)/MBR.bin of=$(BUILD)/$(IMG_NAME) bs=512 count=2 seek=0  conv=notrunc
	dd if=$(BUILD)/MBR.bin of=$(BUILD)/$(IMG_NAME) bs=512 count=2 seek=6  conv=notrunc
# loader 位于磁盘 1 ~ 4 号扇区
	dd if=$(BUILD)/Loader.bin of=$(BUILD)/$(IMG_NAME) bs=512 count=4 seek=2 conv=notrunc
	dd if=$(BUILD)/InitFAT.bin of=$(BUILD)/$(IMG_NAME) bs=512 count=1 seek=8 conv=notrunc
	dd if=$(BUILD)/InitFAT.bin of=$(BUILD)/$(IMG_NAME) bs=512 count=1 seek=2056 conv=notrunc
# kernel
	dd if=$(BUILD)/RootDir.bin of=$(BUILD)/$(IMG_NAME) bs=512 count=1 seek=4104 conv=notrunc
	dd if=$(BUILD)/SimpleOS.out of=$(BUILD)/$(IMG_NAME) bs=512 count=192 seek=4112 conv=notrunc
# Test Program
	$(ROOT)/InstallTestProgram.ps1 $(TEST_PROGRAM)
	
Assets:
# 构建资源非常耗时，因此单独作为一个目标
	$(PAPER)/Assets/MakePDF.ps1 $(BUILD)
Paper:
	New-Item -Type Directory -Force -Path $(BUILD)/Paper
	if (Test-Path $(BUILD)/Paper/main.aux) {Remove-Item $(BUILD)/Paper/main.aux}
	xelatex --shell-escape -8bit --output-dir=$(BUILD)/Paper $(PAPER)/main.tex
# 注意，texlive 根目录下 texlive/2023/texmf-dist/web2c/texmf.cnf 文件中 openout_any 必须设置成 a 或 r，不能为 p
	bibtex $(BUILD)/Paper/main
	xelatex --shell-escape -8bit --output-dir=$(BUILD)/Paper $(PAPER)/main.tex
	xelatex --shell-escape -8bit --output-dir=$(BUILD)/Paper $(PAPER)/main.tex
Slide:
	New-Item -Type Directory -Force -Path $(BUILD)/Slide
	xelatex --shell-escape -8bit -output-dir=$(BUILD)/Slide $(SLIDE)/main.tex
# 清空构建记录
clean: | $(_BUILD)
	Remove-Item -Force -Recurse $(BUILD)